package com.chen.blue.service.business.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chen.blue.converter.business.CompetitionConverter;
import com.chen.blue.domain.delete.business.CompetitionDelete;
import com.chen.blue.domain.delete.business.CompetitionItemDelete;
import com.chen.blue.domain.dto.business.update.CompetitionEdit;
import com.chen.blue.domain.dto.business.update.CompetitionItemEdit;
import com.chen.blue.domain.dto.excel.CompetitionExcel;
import com.chen.blue.domain.model.business.CompetitionItemModel;
import com.chen.blue.domain.model.business.CompetitionModel;
import com.chen.blue.domain.query.business.CompetitionQuery;
import com.chen.blue.domain.vo.business.CompetitionItemVo;
import com.chen.blue.domain.vo.business.CompetitionVo;
import com.chen.blue.exception.e.DtoNullException;
import com.chen.blue.mapper.business.CompetitionMapper;
import com.chen.blue.result.DataResult;
import com.chen.blue.service.business.ICompetitionItemService;
import com.chen.blue.service.business.ICompetitionService;
import com.chen.blue.utils.PageInfoUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author CLT
 * @since 2024-06-20
 */
@Service("iCompetitionService")
public class ICompetitionServiceImpl extends ServiceImpl<CompetitionMapper, CompetitionModel> implements ICompetitionService {

    @Resource
    private ICompetitionItemService iCompetitionItemService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addCompetition(List<CompetitionExcel> excelList) throws DtoNullException {

        if (Objects.isNull(excelList) || excelList.isEmpty())
            throw new DtoNullException("参数为空");


        List<CompetitionExcel> temp = new ArrayList<>();
        Map<Long, List<CompetitionExcel>> tempHas = new HashMap<>();

        /**
         * 没有的赛事留下；有赛事没有赛项的留下
         */
        // 去重
        DataResult<List<CompetitionVo>> listDataResult = competitionList(new CompetitionQuery());
        List<CompetitionVo> competitionVoList = listDataResult.getResult();
        if (Objects.nonNull(competitionVoList) && !competitionVoList.isEmpty()) {
            List<String> tempVar = null;
            List<CompetitionExcel> tempVar6 = null;
            for (CompetitionExcel competitionExcel : excelList) {
                List<String> collect = competitionVoList.stream().map(var6 -> var6.getCompetitionName()).collect(Collectors.toList());
                for (CompetitionVo competitionVo : competitionVoList) {
                    if (competitionVo.getCompetitionName().equals(competitionExcel.getCompetitionName())) {
                        tempVar = competitionVo.getCompetitionItemVos().stream().map(var1 -> var1.getItemName()).collect(Collectors.toList());
                        if (Objects.nonNull(tempVar) && !tempVar.contains(competitionExcel.getItemName())) {
                            // 赛事有了，但是赛项没有，添加到指定的赛事下面
                            if (tempHas.containsKey(competitionVo.getId())) {
                                tempHas.get(competitionVo.getId()).add(competitionExcel);
                            } else {
                                tempVar6 = new ArrayList<>();
                                tempVar6.add(competitionExcel);
                                tempHas.put(competitionVo.getId(), tempVar6);
                            }
                        }
                    } else {
                        // 赛事都没有，直接添加
                        if (!collect.contains(competitionExcel.getCompetitionName())) {
                            temp.add(competitionExcel);
                        }
                    }
                }
            }
        } else {
            temp = excelList;
        }

        /**
         * 添加有赛事但是没有赛项的
         */

        // 赛事有了，但是赛项没有，添加到指定的赛事下面
        List<CompetitionItemModel> tempVar5 = new ArrayList<>();
        CompetitionItemModel competitionItemModelVar1 = null;
        for (Long key : tempHas.keySet()) {
            for (CompetitionExcel competitionExcel : tempHas.get(key)) {
                competitionItemModelVar1 = new CompetitionItemModel();
                BeanUtils.copyProperties(competitionExcel, competitionItemModelVar1);
                competitionItemModelVar1.setCompetitionId(key);
                competitionItemModelVar1.setItemName(competitionExcel.getItemName());
                tempVar5.add(competitionItemModelVar1);
            }
        }

        // 根据赛事和赛项名称进行去重
        List<CompetitionItemModel> tempVar7 = tempVar5.stream().filter(distinctByKey(inner1 -> inner1.getItemName() + "-" + inner1.getCompetitionId())).collect(Collectors.toList());

        boolean b2 = iCompetitionItemService.saveBatch(tempVar7);

        Map<String, Set<CompetitionExcel>> tempVar1 = new HashMap<>();
        Set<CompetitionExcel> tempVar2 = null;

        /**
         * 添加赛事都没有的赛事
         */

        // 将各个赛事及赛项归类
        for (CompetitionExcel competitionExcel : temp) {

            if (!tempVar1.containsKey(competitionExcel.getCompetitionName())) {

                tempVar2 = new HashSet<>();
                tempVar2.add(competitionExcel);
                tempVar1.put(competitionExcel.getCompetitionName(), tempVar2);

            } else {

                tempVar2 = tempVar1.get(competitionExcel.getCompetitionName());
                tempVar2.add(competitionExcel);

            }

        }

        // 转换为对象
        Map<CompetitionModel, List<CompetitionItemModel>> tempVar3 = new HashMap<>();
        CompetitionModel competitionModel = null;
        CompetitionItemModel competitionItemModel = null;
        List<CompetitionItemModel> competitionItemModelList = null;
        boolean isSuccess = false;

        for (String competitionName : tempVar1.keySet()) {

            // 赛事
            competitionModel = new CompetitionModel();
            competitionModel.setCompetitionName(competitionName);

            boolean b1 = super.save(competitionModel);

            // 赛项
            competitionItemModelList = new ArrayList<>();

            for (CompetitionExcel competitionExcel : tempVar1.get(competitionName)) {

                competitionItemModel = new CompetitionItemModel();
                BeanUtils.copyProperties(competitionExcel, competitionItemModel);
                competitionItemModel.setCompetitionId(competitionModel.getId());
                competitionItemModel.setItemName(competitionExcel.getItemName());
                competitionItemModelList.add(competitionItemModel);

            }

            if (b1 && iCompetitionItemService.saveBatch(competitionItemModelList))
                isSuccess = true;

        }

        // 只添加了赛项；添加了赛事和赛项
        return isSuccess || b2;

    }

    @Override
    public List<CompetitionExcel> exportCompetition() {

        List<CompetitionExcel> data = new ArrayList<>();
        CompetitionExcel competitionExcel = null;

        List<CompetitionModel> competitionModelList = super.list();
        List<CompetitionItemModel> competitionItemModelList = iCompetitionItemService.list();

        for (CompetitionModel competitionModel : competitionModelList) {
            for (CompetitionItemModel competitionItemModel : competitionItemModelList) {

                competitionExcel = new CompetitionExcel();
                BeanUtils.copyProperties(competitionItemModel, competitionExcel);
                competitionExcel.setCompetitionName(competitionModel.getCompetitionName());
                competitionExcel.setItemName(competitionItemModel.getItemName());
                data.add(competitionExcel);

            }
        }

        return data;

    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    @Override
    public boolean forbiddenCompetition(CompetitionEdit edit) throws DtoNullException {

        if (Objects.isNull(edit))
            throw new DtoNullException("参数为空");

        LambdaUpdateWrapper<CompetitionModel> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(CompetitionModel::getStatus, edit.getStatus());
        wrapper.eq(CompetitionModel::getId, edit.getId());

        return super.update(CompetitionConverter.dtoEditToModel(edit), wrapper);

    }

    @Override
    public boolean forbiddenItem(CompetitionItemEdit edit) throws DtoNullException {

        if (Objects.isNull(edit))
            throw new DtoNullException("参数为空");

        LambdaUpdateWrapper<CompetitionItemModel> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(CompetitionItemModel::getStatus, edit.getStatus());
        wrapper.eq(CompetitionItemModel::getId, edit.getId());

        CompetitionItemModel competitionItemModel = new CompetitionItemModel();
        BeanUtils.copyProperties(edit, competitionItemModel);

        return iCompetitionItemService.update(competitionItemModel, wrapper);

    }

    @Override
    public boolean deleteItem(CompetitionItemDelete delete) throws DtoNullException {

        if (Objects.isNull(delete))
            throw new DtoNullException("参数为空");

        return Objects.nonNull(delete.getIds()) && !delete.getIds().isEmpty() ? iCompetitionItemService.removeByIds(delete.getIds()) : iCompetitionItemService.removeById(delete.getId());

    }

    @Override
    public boolean deleteCompetition(CompetitionDelete delete) throws DtoNullException {

        if (Objects.isNull(delete))
            throw new DtoNullException("参数为空");

        // 如果下面有赛项则不删除
        List<Long> ids = new ArrayList<>();
        if (Objects.nonNull(delete.getIds()) && !delete.getIds().isEmpty()) {
            for (Long id : delete.getIds()) {
                ids.add(id);
            }
        } else {
            ids.add(delete.getId());
        }
        LambdaQueryWrapper<CompetitionItemModel> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(CompetitionItemModel::getCompetitionId, ids);
        if (!iCompetitionItemService.list(wrapper).isEmpty())
            throw new DtoNullException("存在赛项，无法删除");


        return Objects.nonNull(delete.getIds()) && !delete.getIds().isEmpty() ? super.removeByIds(delete.getIds()) : super.removeById(delete.getId());

    }

    @Override
    public DataResult<List<CompetitionVo>> competitionList(CompetitionQuery query) throws DtoNullException {

        if (Objects.isNull(query))
            throw new DtoNullException("参数为空");

        if ((Objects.nonNull(query.getItemName()) || Objects.nonNull(query.getItemStatus())) && (Objects.isNull(query.getCompetitionName()) && Objects.isNull(query.getCompetitionStatus())))
            throw new DtoNullException("赛项名称和赛项状态必须配合赛事名称和赛事状态使用");

        LambdaQueryWrapper<CompetitionModel> wrapper = new LambdaQueryWrapper<>();

        if (Objects.nonNull(query.getPageNo()) && Objects.nonNull(query.getPageSize()))
            PageHelper.startPage(query.getPageNo(), query.getPageSize());
        if (Objects.nonNull(query.getCompetitionName()))
            wrapper.like(CompetitionModel::getCompetitionName, query.getCompetitionName());
        if (Objects.nonNull(query.getCompetitionStatus()))
            wrapper.eq(CompetitionModel::getStatus, query.getCompetitionStatus());


        List<CompetitionModel> list = super.list(wrapper);
        PageInfo<CompetitionModel> pageInfo = new PageInfo<>(list);
        PageHelper.clearPage();

        /**
         * 数据处理
         */
        List<CompetitionVo> tempVar1 = CompetitionConverter.modelToVoList(pageInfo.getList());
        List<CompetitionItemModel> tempVar2 = iCompetitionItemService.list();
        AtomicReference<CompetitionItemVo> competitionItemVo = new AtomicReference<>();

        List<CompetitionVo> data = Objects.nonNull(tempVar1) && !tempVar1.isEmpty() ? tempVar1.stream().peek(var1 -> {

            List<CompetitionItemVo> tempVar3 = tempVar2.stream()
                    .filter(inner1 -> inner1.getCompetitionId().equals(var1.getId()))
                    .map(inner2 -> {
                        competitionItemVo.set(new CompetitionItemVo());
                        BeanUtils.copyProperties(inner2, competitionItemVo.get());
                        return competitionItemVo.get();
                    }).collect(Collectors.toList());

            List<CompetitionItemVo> tempVar4 = Objects.nonNull(query.getItemName()) ? tempVar3.stream()
                    .filter(inner3 -> inner3.getItemName().startsWith(query.getItemName())).collect(Collectors.toList()) : tempVar3;

            List<CompetitionItemVo> tempVar5 = Objects.nonNull(query.getItemStatus()) ? tempVar4.stream()
                    .filter(inner4 -> inner4.getStatus().equals(query.getItemStatus())).collect(Collectors.toList()) : tempVar4;

            var1.setCompetitionItemVos(tempVar5);

        }).collect(Collectors.toList()) : null;

        /**
         * 统一返回
         */
        DataResult<List<CompetitionVo>> dataResult = new DataResult<>();
        dataResult.setData(data);

        PageInfoUtil.setPageInfo(dataResult, pageInfo);

        return dataResult;

    }

    @Override
    public DataResult<List<CompetitionVo>> competitionListSelect() throws DtoNullException {

        CompetitionQuery competitionQuery = new CompetitionQuery();
        competitionQuery.setCompetitionStatus(true);
        competitionQuery.setItemStatus(true);

        return competitionList(competitionQuery);

    }


}
